package com.tinklabs.demo.utils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;


/**
 * 提供Gson处理的工具类
 *
 * @date 2016/07/20. 12:18
 * @editor
 * @date
 * @describe
 */
public class GsonUtils {

    private static Gson gson;
    private static Gson fillGson;
    private static Gson intGson;

    /**
     * 唯一 gson
     */

    public static Gson getInstance() {
        if (gson == null) {
            synchronized (GsonUtils.class) {
                if (gson == null) {
                    gson = new Gson();
                }
            }
        }
        return gson;
    }

    public static Gson getFillInstance() {
        if (fillGson == null) {
            synchronized (GsonUtils.class) {
                if (fillGson == null) {
                    fillGson = new GsonBuilder().serializeNulls().create();
                }
            }
        }

        return fillGson;
    }


    public static Gson getIntInstance() {
        if (intGson == null) {
            intGson = new GsonBuilder()//
                    .registerTypeAdapter(Integer.class, INTEGER)//
                    .registerTypeAdapter(Double.class, new DoubleTypeAdapter())//
                    .create();
        }
        return intGson;
    }

    public static class DoubleTypeAdapter implements JsonSerializer<Double> {
        @Override
        public JsonElement serialize(Double d, Type type, JsonSerializationContext context) {
            DecimalFormat format = new DecimalFormat("##0.00");
            String temp = format.format(d);
            System.out.println(temp);
            JsonPrimitive pri = new JsonPrimitive(temp);
            return pri;
        }
    }

    public static final TypeAdapter<Number> INTEGER = new TypeAdapter<Number>() {
        @Override
        public Number read(JsonReader in) throws IOException {
            if (in.peek() == JsonToken.NULL) {
                in.nextNull();
                return 0;
            }
            try {
                double i = in.nextDouble();//当成double来读取
                return (int) i;//强制转为int
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }


        @Override
        public void write(JsonWriter out, Number value) throws IOException {

            out.value(value);
        }
    };

    /**
     * 功能描述：把JSON数据转换成普通字符串列表
     *
     * @param jsonData
     * @return JSON数据
     * @throws Exception
     */
    public static List<String> getStringList(String jsonData) throws Exception {
        return getInstance().fromJson(jsonData, new TypeToken<List<String>>() {
        }.getType());
    }

    /**
     * 功能描述：把JSON数据转换成指定的java对象
     *
     * @param jsonData JSON数据
     * @param clazz    指定的java对象
     * @return
     * @throws Exception
     */

    public static <T> T getSingleBean(String jsonData, Class<T> clazz) throws Exception {
        return getInstance().fromJson(jsonData, clazz);
    }

    /**
     * 功能描述：把JSON数据转换成指定的java对象列表
     *
     * @param jsonData JSON数据
     * @return
     * @throws Exception
     */
    public static <T> List<T> getBeanList(String jsonData) throws Exception {
        return getInstance().fromJson(jsonData, new TypeToken<List<T>>() {
        }.getType());
    }

    /**
     * 功能描述：把JSON数据转换成较为带有泛型的列表
     *
     * @param jsonData
     * @return JSON数据
     * @throws Exception
     */
    public static <T, clazz> List<T> getBeanList(String jsonData, Class<T> tClass) throws Exception {
        return getInstance().fromJson(jsonData, new TypeToken<List<clazz>>() {
        }.getType());
    }

    /**
     * 功能描述：把JSON数据转换成较为复杂的java对象列表
     *
     * @param jsonData
     * @return JSON数据
     * @throws Exception
     */
    public static List<Map<String, Object>> getBeanMapList(String jsonData) throws Exception {
        return getInstance().fromJson(jsonData, new TypeToken<List<Map<String, Object>>>() {
        }.getType());
    }

    /**
     * 功能描述：Object对象转化成json数据
     *
     * @param
     * @return JSON数据
     */
    public static String toJson(Object object) {
        String json = getInstance().toJson(object);
        return json;
    }

    /**
     * 用来检测一个jsonStr字符串是否是object类型，还是array类型
     * 0：既不是array也不是object
     * 1：是object
     * 2：是Array
     *
     * @param jsonStr
     * @return
     */
    public static JsonTypeEnum checkJsonIsArrayOrObject(String jsonStr) {
        try {
            JSONArray array = new JSONArray(jsonStr);
            return JsonTypeEnum.JsonArray;
        } catch (JSONException e) {// 抛错 说明JSON字符不是数组或根本就不是JSON
            try {
                JSONObject object = new JSONObject(jsonStr);
                return JsonTypeEnum.JsonObj;
            } catch (JSONException e2) {// 抛错 说明JSON字符根本就不是JSON
                //LogUtils.I("Log_Jennifer", "不符合JSON解析的数据源:\n" + jsonStr);
                return JsonTypeEnum.Value;
            }
        }
    }

    public enum JsonTypeEnum {
        JsonObj, JsonArray, Value;
    }
}
